/* 
 * File: Vector2
 * Created: 16-JUN-2011
 * Author: Colin Gall-McDaid
 * 
 * Description: 2D vector math class.
 * NOTE: Makes some use of Android specific FloatMath API. For non-Android platforms
 * use the standard Java Math library.
 */
package com.gallsoft.games.framework.math;

import android.util.FloatMath;


public class Vector2 {

    public static float TO_RADIANS = (1 / 180.0f) * (float)Math.PI;
    public static float TO_DEGREES = (1 / (float)Math.PI) * 180;
    public float x, y;
    
    public Vector2() {        
    }
    
    public Vector2(float x, float y) {
        this.x = x;
        this.y = y;
    }
    
    public Vector2(Vector2 other) {
        this.x = other.x;
        this.y = other.y;
    }
    
    /**
     * Copy a vector
     * 
     * @return new vector
     */
    public Vector2 cpy() {
        return new Vector2(x, y);
    }

    /**
     * Set a vector using float values
     * 
     * @param x
     *      x coordinate
     * @param y
     *      y coordinate
     * @return
     *      original vector with new values
     */
    public Vector2 set(float x, float y) {
        this.x = x;
        this.y = y;
        return this;
    }
    
    /**
     * Set a vector using another vector
     * 
     * @param other
     *      vector used to set coordinates
     * @return
     *      original vector with new values
     */
    public Vector2 set(Vector2 other) {
        this.x = other.x;
        this.y = other.y;
        return this;
    }
    
    /**
     * Add to vector using float values
     * 
     * @param x
     *      x coordinate
     * @param y
     *      y coordinate
     * @return
     *      original vector with adjusted values
     */
    public Vector2 add(float x, float y) {
        this.x += x;
        this.y += y;
        return this;
    }
    
    /**
     * Add to a vector using another vector
     * 
     * @param other
     *      vector to add
     * @return
     *      original vector with adjusted values
     */
    public Vector2 add(Vector2 other) {
        this.x += other.x;
        this.y += other.y;
        return this;
    }

    /**
     * Subract from vector using float values
     * 
     * @param x
     *      x coordinate
     * @param y
     *      y coordinate
     * @return
     *      original vector with adjusted values
     */
    public Vector2 sub(float x, float y) {
        this.x -= x;
        this.y -= y;
        return this;
    }
    
    /**
     * Subtract from a vector using another vector
     * 
     * @param other
     *      vector to add
     * @return
     *      original vector with adjusted values
     */
    public Vector2 sub(Vector2 other) {
        this.x -= other.x;
        this.y -= other.y;
        return this;
    }

    /**
     * Multiply a vector by a scalar value
     * 
     * @param other
     *      vector to multiply by
     * @return
     *      original vector with adjusted values
     */
    public Vector2 mul(float scalar) {
        this.x *= scalar;
        this.y *= scalar;
        return this;
    }
    
    /**
     * Calculate the length of a vector.
     * NOTE: Uses Android specific FloatMath API which uses floats instead of
     * doubles. This is a little faster than the standard Java Math API.
     * 
     * @return
     *      vector length
     */
    public float len() {
        return FloatMath.sqrt(x * x + y * y);
    }
    
    /**
     * Normalise a vector
     * 
     * @return
     *      normalised version of original vector
     */
    public Vector2 nor() {
        float len = len();
        
        if (len != 0) {
            this.x /= len;
            this.y /= len;
        }
        
        return this;
    }
    
    /**
     * Calculate the angle between a vector and the x-axis
     * 
     * @return
     *      angle between vector and x-axis in degrees
     */
    public float angle() {
        float angle = (float)Math.atan2(y, x) * TO_DEGREES;
        
        if (angle < 0)
            angle += 360;
        
        return angle;
    }
    
    /**
     * Rotate a vector by given angle
     * 
     * @param angle
     *      angle to rotate vector 
     * @return
     *      original vector with adjusted values
     */
    public Vector2 rotate(float angle) {
        float rad = angle * TO_RADIANS;
        float cos = FloatMath.cos(rad);
        float sin = FloatMath.sin(rad);
        
        //float newX = this.x * cos - this.y * sin;
        //float newY = this.x * sin + this.y * cos;
        
        //this.x = newX;
        //this.y = newY;
        
        this.x = this.x * cos - this.y * sin;
        this.y = this.x * sin + this.y * cos;
        
        return this;
    }
    
    /**
     * Calculate the distance from another vector
     * 
     * @param other
     *      the other vector
     * @return
     *      the distance
     */
    public float dist(Vector2 other) {
        float distX = this.x - other.x;
        float distY = this.y - other.y;
        return FloatMath.sqrt(distX * distY + distY * distY);
    }
    
    /**
     * Calculate the distance from another position
     * 
     * @param x
     *      x coordinate
     * @param y
     *      y coordinate
     * @return
     *      the distance
     */
    public float dist(float x, float y) {
        float distX = this.x - x;
        float distY = this.y - y;
        return FloatMath.sqrt(distX * distY + distY * distY);
    }
    
    /**
     * Calculate distance from another vector without need for square root call
     * 
     * @param other
     *      the other vector
     * @return
     *      the distance
     */
    public float distSquared(Vector2 other) {
        float distX = this.x - other.x;
        float distY = this.y - other.y;
        return distX * distX + distY * distY;
    }
    
    /**
     * Calculate distance from another position without need for square root call
     * 
     * @param x
     *      x coordinate
     * @param y
     *      y coordinate
     * @return
     *      the distance
     */
    public float distSquared(float x, float y) {
        float distX = this.x - x;
        float distY = this.y - y;
        return distX * distX + distY * distY;
    }

}
